#include "bsp.h"
#include <string.h>
#include <stdlib.h>
#include <tsfilter.h>
#include <stdio.h>
#include <math.h>
#include "touchscreen.h"

#define PEN_Read() ((GPIOA->IDR & GPIO_PIN_5) != 0) /* 读PEN线状态 */
lv_indev_t * indev_touchpad;

/*Initialize your touchpad*/
static void touchpad_init(void)
{
    /*Your code comes here*/
}
/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
    /*Your code comes here*/

    return false;
}

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    /*Your code comes here*/

    (*x) = 0;
    (*y) = 0;
}

/* Will be called by the library to read the touchpad */
static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static lv_coord_t last_x = 0;
    static lv_coord_t last_y = 0;

    /*Save the pressed coordinates and the state*/
    if(touchpad_is_pressed()) {
        touchpad_get_xy(&last_x, &last_y);
        data->state = LV_INDEV_STATE_PR;
    } else {
        data->state = LV_INDEV_STATE_REL;
    }

    /*Set the last pressed coordinates*/
    data->point.x = last_x;
    data->point.y = last_y;

    /*Return `false` because we are not buffering and no more data to read*/
    return false;
}



void lv_port_indev_init(void)
{


    lv_indev_drv_t indev_drv;


    /*Initialize your touchpad if you have*/
    touchpad_init();

    /*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touchpad_read;
    indev_touchpad = lv_indev_drv_register(&indev_drv);

 
}







/*
*********************************************************************************************************
*	函 数 名: OV_WriteReg
*	功能说明: 写ns2009寄存器
*	形    参: _ucRegAddr  : 寄存器地址
*			  _ucRegValue : 寄存器值
*	返 回 值: 无
*********************************************************************************************************
*/
static void ns2009_WriteReg(uint8_t _ucRegAddr, uint8_t _ucRegValue)
{
    i2c_Start();							/* 总线开始信号 */

    i2c_SendByte(NS2009_SLV_ADDR);		/* 发送设备地址+写信号 */
	  i2c_WaitAck();

    i2c_SendByte(_ucRegAddr);				/* 发送寄存器地址 */
	  i2c_WaitAck();

    i2c_SendByte(_ucRegValue);				/* 发送寄存器数值 */
	  i2c_WaitAck();

    i2c_Stop();                   			/* 总线停止信号 */
}

/*
*********************************************************************************************************
*	函 数 名: ns2009_ReadReg,连读两次，对应12位ADC
*	功能说明: 读ns2009寄存器
*	形    参: _ucRegAddr  : 寄存器地址
*	返 回 值: 寄存器值
*********************************************************************************************************
*/
static uint16_t ns2009_ReadReg(uint8_t _ucRegAddr)
{
	uint16_t usRegValue;
  u16 Hbytes,Lbytes;
	i2c_Start();                  			/* 总线开始信号 */
	i2c_SendByte(NS2009_SLV_ADDR);		/* 发送设备地址+写信号 */
	i2c_WaitAck();
	i2c_SendByte(_ucRegAddr);				/* 发送地址 */
	i2c_WaitAck();
	i2c_Start();							/* 总线开始信号 */
	i2c_SendByte(NS2009_SLV_ADDR + 1);/* 发送设备地址+读信号 */
	i2c_WaitAck();
	Hbytes = i2c_ReadByte();       		/* 读出高字节数据 */
	i2c_NAck();
	Lbytes = i2c_ReadByte();       		/* 读出高字节数据 */
	i2c_NAck();
	i2c_Stop();                  			/* 总线停止信号 */
	usRegValue = (((Hbytes<<8) + Lbytes) >>4);  //AD有效位数是12，除去后面4个0 
	return usRegValue;
}

static uint8_t ns2009_read(uint8_t cmd, int *val)
{
    *val = ns2009_ReadReg(cmd);
    return 1;
}

static void push_event_begin(struct ts_ns2009_event_t *ts_event, int x, int y)
{
    ts_event->type = TOUCH_BEGIN;
    ts_event->x = x;
    ts_event->y = y;
}

static void push_event_move(struct ts_ns2009_event_t *ts_event, int x, int y)
{
    ts_event->type = TOUCH_MOVE;
    ts_event->x = x;
    ts_event->y = y;
}

static void push_event_end(struct ts_ns2009_event_t *ts_event, int x, int y)
{
    ts_event->type = TOUCH_END;
    ts_event->x = x;
    ts_event->y = y;
}

static void push_event_none(struct ts_ns2009_event_t *ts_event)
{
    ts_event->type = TOUCH_NONE;
    ts_event->x = 0;
    ts_event->y = 0;
}
//#define PEN
int ts_ns2009_poll(struct ts_ns2009_pdata_t *ts_ns2009_pdata)
{
    int x = 0, y = 0, z1 = 0;
#ifdef PEN
    if (PEN_Read() == 0)
    {
        ns2009_read(NS2009_LOW_POWER_READ_Z1, &z1);
        if ((z1 > 70) && (z1 < 3000)) //这个常量不确定怎么来的 实测不动的状态下是255
        {
            ns2009_read(NS2009_LOW_POWER_READ_X, &x);
            ns2009_read(NS2009_LOW_POWER_READ_Y, &y);
            tsfilter_update(ts_ns2009_pdata->filter, &x, &y);

            if (!ts_ns2009_pdata->press)
            {
                push_event_begin(ts_ns2009_pdata->event, x, y);
                ts_ns2009_pdata->press = 1;
            }
            else
            {
                if ((ts_ns2009_pdata->x != x) || (ts_ns2009_pdata->y != y))
                {
                    push_event_move(ts_ns2009_pdata->event, x, y);
                }
            }
            ts_ns2009_pdata->x = x;
            ts_ns2009_pdata->y = y;
        }
        else
        {
            if (ts_ns2009_pdata->press)
            {
                tsfilter_clear(ts_ns2009_pdata->filter);
                push_event_end(ts_ns2009_pdata->event, ts_ns2009_pdata->x, ts_ns2009_pdata->y);
                ts_ns2009_pdata->press = 0;
            }
        }
    }
    else
    {
        push_event_none(ts_ns2009_pdata->event);
    }
#endif
#ifndef PEN	
	if (ns2009_read(NS2009_LOW_POWER_READ_Z1, &z1))
    {
        if ((z1 > 70) && (z1 < 2000))
        {
            ns2009_read(NS2009_LOW_POWER_READ_X, &x);
            ns2009_read(NS2009_LOW_POWER_READ_Y, &y);
            tsfilter_update(ts_ns2009_pdata->filter, &x, &y);

            if (!ts_ns2009_pdata->press)
            {
                push_event_begin(ts_ns2009_pdata->event, x, y);
                ts_ns2009_pdata->press = 1;
            }
            else
            {
                if ((ts_ns2009_pdata->x != x) || (ts_ns2009_pdata->y != y))
                {
                    push_event_move(ts_ns2009_pdata->event, x, y);
                }
            }
            ts_ns2009_pdata->x = x;
            ts_ns2009_pdata->y = y;
        }
        else
        {
            if (ts_ns2009_pdata->press)
            {
                tsfilter_clear(ts_ns2009_pdata->filter);
                push_event_end(ts_ns2009_pdata->event, ts_ns2009_pdata->x, ts_ns2009_pdata->y);
                ts_ns2009_pdata->press = 0;
            }
        }
    }
    else
    {
        push_event_none(ts_ns2009_pdata->event);
    }
#endif
    return 1;
}

int ts_ns2009_set_calibration(struct ts_ns2009_pdata_t *ts_ns2009_pdata, int cmd, void *arg)
{
    int cal[7];

    if (cmd == NS2009_IOCTL_SET_CALBRATION)
    {
        if (!arg)
            return -1;
        memcpy(cal, arg, sizeof(int) * 7);
        tsfilter_setcal(ts_ns2009_pdata->filter, cal);
        return 0;
    }
    return -1;
}

// "ts-ns2009@0" : {
//     "i2c-bus" : "i2c-v3s.0",
//     "slave-address" : 72,
//     "median-filter-length" : 5,
//     "mean-filter-length" : 5,
//     "calibration" : [ -8374,8374,12287936,-5329,5329,9011200,65536 ],
//     "poll-interval-ms" : 10
// },

//-8374,8374,12287936,-5329,5329,9011200,65536

struct ts_ns2009_pdata_t *ts_ns2009_probe(int* cal)
{
    struct ts_ns2009_pdata_t *ts_ns2009_pdata;
    ns2009_read(NS2009_LOW_POWER_READ_Z1, NULL);
    touchscreen_malloc(sizeof(struct ts_ns2009_pdata_t));
    ts_ns2009_pdata->filter = tsfilter_alloc(5, 5);
    tsfilter_setcal(ts_ns2009_pdata->filter, cal);
    //
    ts_ns2009_pdata->x = 0;
    ts_ns2009_pdata->y = 0;
    ts_ns2009_pdata->press = 0;
    //
    ts_ns2009_pdata->event = touchscreen_malloc(sizeof(struct ts_ns2009_event_t));
    ts_ns2009_pdata->event->x = 0;
    ts_ns2009_pdata->event->y = 0;
    ts_ns2009_pdata->event->type = TOUCH_NONE;
    return ts_ns2009_pdata;
}

void ts_ns2009_remove(struct ts_ns2009_pdata_t *ts_ns2009_pdata)
{
    if (ts_ns2009_pdata->filter)
    {
        tsfilter_free(ts_ns2009_pdata->filter);
        ts_ns2009_pdata->filter = NULL;
    }

    if (ts_ns2009_pdata->event)
    {
        touchscreen_free(ts_ns2009_pdata->event);
        ts_ns2009_pdata->filter = NULL;
    }

    if (ts_ns2009_pdata)
    {
        touchscreen_free(ts_ns2009_pdata);
        ts_ns2009_pdata->filter = NULL;
    }
}
